package edu.vt.ece.main;

import edu.vt.ece.util.AVLTree;
import edu.vt.ece.util.ConcurrentAVLTree;

import java.util.Random;

/**
 * User: Jeremy Tate and Brian Cheng
 * Date: 11/23/11
 * Time: 10:12 PM
 *
 * This is the class that will be used to test concurrent operations on the AVL tree
 */
public class AVLThread extends Thread
{
	private int loopCount;
	private AVLTree tree;
	private Random random;
	private boolean debug = false;
	private boolean courseGrainLock = false;

	public AVLThread (int loopCount, AVLTree tree, boolean debugMode)
	{
		this.loopCount = loopCount;
		this.tree = tree;
		random = new Random();
		this.debug = debugMode;
		if (tree instanceof ConcurrentAVLTree)
		{
			courseGrainLock = false;
		}
	}

	public void run()
	{
		long start = System.currentTimeMillis();
		System.out.println("running " + this.getId()); 
		for (int i = 1; i <= loopCount; i++)
		{
			int operation = Math.abs(random.nextInt() % 100);
			if(operation>=0 && operation<(Tester.ADD_PROBABILITY -1)) operation = 0;
			else if(operation>=Tester.ADD_PROBABILITY && operation<(Tester.CONTAINS_PROBABILITY -1)) operation = 1;
			else if(operation>=Tester.ADD_PROBABILITY+Tester.CONTAINS_PROBABILITY && operation<100) operation = 2;
			
			int tmpInt = Math.abs(random.nextInt() % 1000);
			
			//add or remove or contains
			if (courseGrainLock)
			{
				tree.getTreeLock();
			}
			if (debug)System.out.println(this.getId() + " just got lock. perform operation " + operation);
			switch(operation) {
				case 0: {
					if(!tree.add(tmpInt)) {
						if(debug) System.out.println(this.getId() + " Failed to add " + tmpInt);
					}
					break;
				}
				case 1: {
					if (tree.contains(tmpInt) != null) {
						if(debug) System.out.println(this.getId() + " Tree does contain " + tmpInt);
					}
					else {
						if(debug) System.out.println(this.getId() + " Tree does not contain " + tmpInt);
					}
					break;
				}
				case 2: {
					if(tree.remove(tmpInt)) {
						if(debug) System.out.println(this.getId() + " Successfully removed " + tmpInt);
					} else {
						if(debug) System.out.println(this.getId() + " Failed to remove " + tmpInt);
					}
					break;
				}
			}
			if (debug) System.out.println(this.getId() + " finished operation " + operation + ". release lock now");
			if (courseGrainLock)
			{
				tree.releaseTreeLock();
			}
		}
		System.out.println("Thread [" + this.getId() + "] done in [" + (System.currentTimeMillis() - start) + "] ms");
	}
}
